"""
路线规划视图
"""
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework.throttling import UserRateThrottle, AnonRateThrottle
try:
    from celery.result import AsyncResult
    _CELERY_AVAILABLE = True
except Exception:
    AsyncResult = None
    _CELERY_AVAILABLE = False
from django.db import transaction, models
from django.core.cache import cache
from django.conf import settings
from django.utils.crypto import get_random_string
from django.db.models import F
from apps.attractions.models import Attraction
from apps.routes.models import RoutePlan, RouteFavorite
from apps.routes.serializers import RoutePlanSerializer, RoutePlanResponseSerializer
from apps.routes.tasks import plan_route_task
from apps.routes.algorithms import TravelDijkstra, MultiFactorWeight, TSPOptimizer
from utils.distance_calculator import DistanceCalculator
from utils.number_formatter import format_price, format_distance, format_coordinate


class RoutePlanThrottle(UserRateThrottle):
    """路线规划限流（更严格的限制）"""
    rate = '20/hour'  # 每小时20次


class RoutePlanView(APIView):
    """路线规划视图"""
    throttle_classes = [RoutePlanThrottle]  # 应用限流
    
    def post(self, request):
        """
        规划路线（使用缓存优化，增强错误处理和验证）
        """
        # 输入验证
        serializer = RoutePlanSerializer(data=request.data)
        if not serializer.is_valid():
            return Response({
                'error': '输入数据验证失败',
                'details': serializer.errors
            }, status=status.HTTP_400_BAD_REQUEST)
        
        # 验证必访景点数量（防止过多景点导致性能问题）
        must_visit = serializer.validated_data.get('must_visit', [])
        if len(must_visit) > 20:
            return Response({
                'error': '必访景点数量不能超过20个',
                'details': f'当前数量: {len(must_visit)}'
            }, status=status.HTTP_400_BAD_REQUEST)
        
        data = serializer.validated_data
        budget = float(data['budget'])
        start_attraction_id = data['start_attraction_id']
        must_visit = data.get('must_visit', [])
        priority = data.get('priority', 'balanced')
        transport_mode = data.get('transport_mode', 'driving')
        start_time = data.get('start_time')  # TimeField对象
        max_total_time = data.get('max_total_time')  # 分钟数
        
        # 转换开始时间为字符串格式
        start_time_str = None
        if start_time:
            start_time_str = start_time.strftime('%H:%M')
        
        # 构建缓存键（包含交通方式和时间约束）
        must_visit_sorted = sorted(must_visit) if must_visit else []
        time_key = f'{start_time_str}_{max_total_time}' if start_time_str or max_total_time else 'no_time'
        cache_key = f'route_plan_{start_attraction_id}_{"_".join(map(str, must_visit_sorted))}_{budget}_{priority}_{transport_mode}_{time_key}'
        
        # 尝试从缓存获取
        cached_result = cache.get(cache_key)
        if cached_result:
            return Response(cached_result)
        
        try:
            # 获取起始景点（使用select_related优化）
            start_attraction = Attraction.objects.select_related().get(id=start_attraction_id)
            
            # 获取所有相关景点（使用select_related优化）
            attraction_ids = [start_attraction_id] + must_visit
            attractions = Attraction.objects.select_related().filter(id__in=attraction_ids)
            
            if attractions.count() != len(attraction_ids):
                return Response(
                    {'error': '部分景点不存在'},
                    status=status.HTTP_400_BAD_REQUEST
                )
            
            # 构建图结构（考虑交通方式）
            graph = self._build_graph(attraction_ids, transport_mode)
            
            # 获取景点信息字典（用于时间约束检查，使用select_related优化）
            attractions_dict = {attr.id: attr for attr in Attraction.objects.select_related().filter(id__in=attraction_ids)}
            
            # 根据优先级设置权重
            weight_config = self._get_weight_config(priority)
            
            # 如果必访景点数量较多，先使用TSP优化访问顺序
            optimized_must_visit = must_visit
            if len(must_visit) > 1:
                tsp_optimizer = TSPOptimizer(graph, weight_config)
                optimized_order = tsp_optimizer.optimize_visit_order(start_attraction_id, must_visit)
                # 从优化后的顺序中提取必访景点（排除起始景点）
                optimized_must_visit = [x for x in optimized_order if x != start_attraction_id]
            
            # 创建Dijkstra算法实例（传入时间约束和景点信息）
            dijkstra = TravelDijkstra(
                graph, 
                budget, 
                weight_config,
                start_time=start_time_str,
                max_total_time=max_total_time,
                attractions_info=attractions_dict
            )
            
            # 计算最优路线（使用优化后的必访景点顺序）
            optimal_route_ids, total_weight, total_cost, total_distance = \
                dijkstra.find_optimal_routes(start_attraction_id, optimized_must_visit)
            
            # 构建路线详情（包含时间信息）
            route_details = self._build_route_details(
                optimal_route_ids, 
                graph, 
                start_time_str=start_time_str,
                attractions_info=attractions_dict
            )
            
            # 保存路线规划记录
            route_plan = RoutePlan.objects.create(
                user_id=request.user.id if request.user.is_authenticated else None,
                budget=budget,
                start_attraction_id=start_attraction_id,
                must_visit_attractions=must_visit,
                transport_mode=transport_mode,
                optimal_route={
                    'route': optimal_route_ids,
                    'details': route_details
                },
                total_cost=total_cost,
                total_distance=total_distance
            )
            
            # 计算总时间
            total_time = 0
            if route_details:
                last_detail = route_details[-1]
                if last_detail.get('departure_time'):
                    # 从离开时间计算总时间
                    departure_parts = last_detail['departure_time'].split(':')
                    departure_minutes = int(departure_parts[0]) * 60 + int(departure_parts[1])
                    if start_time_str:
                        start_parts = start_time_str.split(':')
                        start_minutes = int(start_parts[0]) * 60 + int(start_parts[1])
                        total_time = departure_minutes - start_minutes
                    else:
                        # 如果没有开始时间，从第一个景点的到达时间计算
                        first_detail = route_details[0]
                        if first_detail.get('arrival_time'):
                            arrival_parts = first_detail['arrival_time'].split(':')
                            arrival_minutes = int(arrival_parts[0]) * 60 + int(arrival_parts[1])
                            total_time = departure_minutes - arrival_minutes
            
            # 构建响应数据
            response_data = {
                'id': route_plan.id,
                'budget': float(format_price(budget)),
                'start_attraction_id': start_attraction_id,
                'must_visit_attractions': must_visit,
                'transport_mode': transport_mode,
                'start_time': start_time_str,
                'max_total_time': max_total_time,
                'optimal_route': {
                    'route': optimal_route_ids,
                    'details': route_details
                },
                'total_cost': float(format_price(total_cost)),
                'total_distance': float(format_distance(total_distance)),
                'total_time': total_time,
                'created_at': route_plan.created_at.isoformat()
            }
            
            # 缓存结果（仅缓存成功的路线规划）
            cache.set(cache_key, response_data, settings.CACHE_TIMEOUT.get('route_results', 3600))
            
            return Response(response_data, status=status.HTTP_201_CREATED)
            
        except ValueError as e:
            return Response(
                {'error': str(e)},
                status=status.HTTP_400_BAD_REQUEST
            )
        except Exception as e:
            import traceback
            import logging
            logger = logging.getLogger(__name__)
            error_trace = traceback.format_exc()
            logger.error(f'路线规划失败: {str(e)}\n{error_trace}')
            return Response(
                {'error': f'路线规划失败: {str(e)}', 'detail': str(e)},
                status=status.HTTP_500_INTERNAL_SERVER_ERROR
            )
    
    def _build_graph(self, attraction_ids, transport_mode='driving'):
        """
        构建图结构（支持多种交通方式，使用缓存优化）
        :param attraction_ids: 景点ID列表
        :param transport_mode: 交通方式
        :return: 图数据结构
        """
        graph = {}
        calculator = DistanceCalculator()
        
        # 构建距离矩阵缓存键
        sorted_ids = sorted(attraction_ids)
        distance_cache_key = f'distance_matrix_{"_".join(map(str, sorted_ids))}_{transport_mode}'
        
        # 尝试从缓存获取距离矩阵
        cached_matrix = cache.get(distance_cache_key)
        
        # 获取所有景点信息
        attractions = {attr.id: attr for attr in Attraction.objects.filter(id__in=attraction_ids)}
        
        # 构建图的边
        for origin_id in attraction_ids:
            graph[origin_id] = {}
            for dest_id in attraction_ids:
                if origin_id == dest_id:
                    continue
                
                # 尝试从缓存的距离矩阵获取
                distance_data = None
                if cached_matrix and origin_id in cached_matrix and dest_id in cached_matrix[origin_id]:
                    distance_data = cached_matrix[origin_id][dest_id]
                else:
                    # 计算距离（考虑交通方式）
                    distance_data = calculator.calculate_distance(
                        origin_id, dest_id, transport_mode=transport_mode
                    )
                
                # 获取目标景点的门票价格和热度
                dest_attr = attractions[dest_id]
                
                # 计算总费用（交通费用 + 门票价格）
                transport_cost = float(distance_data.get('transport_cost', 0))
                ticket_price = float(dest_attr.ticket_price or 0)
                total_cost = transport_cost + ticket_price
                
                graph[origin_id][dest_id] = {
                    'distance': float(format_distance(distance_data.get('distance', 0))),
                    'cost': float(format_price(total_cost)),
                    'time': distance_data.get('travel_time', 0) + (dest_attr.visit_time or 60),
                    'popularity': dest_attr.popularity or 0,
                    'transport_mode': transport_mode
                }
        
        # 缓存距离矩阵（如果之前没有缓存）
        if not cached_matrix:
            # 构建距离矩阵
            distance_matrix = {}
            for origin_id in attraction_ids:
                distance_matrix[origin_id] = {}
                for dest_id in attraction_ids:
                    if origin_id != dest_id:
                        distance_matrix[origin_id][dest_id] = graph[origin_id][dest_id]
            
            # 缓存距离矩阵（24小时）
            cache.set(distance_cache_key, distance_matrix, 86400)
        
        return graph
    
    def _get_weight_config(self, priority):
        """
        根据优先级获取权重配置
        :param priority: 优先级（distance, cost, balanced）
        :return: MultiFactorWeight实例
        """
        if priority == 'distance':
            return MultiFactorWeight(distance_weight=0.8, cost_weight=0.2)
        elif priority == 'cost':
            return MultiFactorWeight(distance_weight=0.3, cost_weight=0.7)
        else:  # balanced
            return MultiFactorWeight(distance_weight=0.6, cost_weight=0.4)
    
    def _build_route_details(self, route_ids, graph, start_time_str=None, attractions_info=None):
        """
        构建路线详情（包含时间信息）
        :param route_ids: 路线景点ID列表
        :param graph: 图结构
        :param start_time_str: 开始时间字符串（HH:MM）
        :param attractions_info: 景点信息字典
        :return: 路线详情列表
        """
        details = []
        attractions = attractions_info or {attr.id: attr for attr in Attraction.objects.filter(id__in=route_ids)}
        
        # 计算当前时间（分钟数）
        current_time_minutes = 0
        if start_time_str:
            try:
                parts = start_time_str.split(':')
                current_time_minutes = int(parts[0]) * 60 + int(parts[1])
            except (ValueError, AttributeError):
                current_time_minutes = 0
        
        for i in range(len(route_ids)):
            attraction_id = route_ids[i]
            attraction = attractions.get(attraction_id)
            if not attraction:
                continue
            
            visit_time = attraction.visit_time if attraction.visit_time else 60
            
            # 计算交通时间（从上一站到当前站）
            transport_time = 0
            if i > 0:
                prev_id = route_ids[i-1]
                if prev_id in graph and attraction_id in graph[prev_id]:
                    edge_data = graph[prev_id][attraction_id]
                    transport_time = edge_data.get('time', 0)
            
            # 计算到达时间和离开时间
            arrival_time_minutes = current_time_minutes + transport_time
            departure_time_minutes = arrival_time_minutes + visit_time
            
            # 转换为时间字符串
            arrival_time_str = self._minutes_to_time_str(arrival_time_minutes)
            departure_time_str = self._minutes_to_time_str(departure_time_minutes)
            
            detail = {
                'attraction_id': attraction_id,
                'attraction_name': attraction.name,
                'latitude': float(format_coordinate(attraction.latitude)),
                'longitude': float(format_coordinate(attraction.longitude)),
                'ticket_price': float(format_price(attraction.ticket_price)),
                'visit_time': visit_time,
                'order': i + 1,
                'arrival_time': arrival_time_str,
                'departure_time': departure_time_str,
                'open_time': attraction.open_time.strftime('%H:%M') if attraction.open_time else None,
                'close_time': attraction.close_time.strftime('%H:%M') if attraction.close_time else None,
            }
            
            # 添加到达该景点的信息
            if i > 0:
                prev_id = route_ids[i-1]
                if prev_id in graph and attraction_id in graph[prev_id]:
                    edge_data = graph[prev_id][attraction_id]
                    detail['from_previous'] = {
                        'distance': float(format_distance(edge_data.get('distance', 0))),
                        'cost': float(format_price(edge_data.get('cost', 0))),
                        'time': transport_time
                    }
            
            details.append(detail)
            
            # 更新当前时间（离开时间）
            current_time_minutes = departure_time_minutes
        
        return details
    
    def _minutes_to_time_str(self, minutes: int) -> str:
        """
        将分钟数转换为时间字符串
        :param minutes: 分钟数（从00:00开始）
        :return: 时间字符串，格式：HH:MM
        """
        hours = minutes // 60
        mins = minutes % 60
        return f"{hours:02d}:{mins:02d}"


class RoutePlanHistoryViewSet(viewsets.ReadOnlyModelViewSet):
    """路线规划历史视图集"""
    queryset = RoutePlan.objects.all()
    serializer_class = RoutePlanResponseSerializer
    
    def get_serializer_context(self):
        """添加request到序列化器context"""
        context = super().get_serializer_context()
        context['request'] = self.request
        return context
    
    def get_queryset(self):
        """获取当前用户的路线规划历史（优化查询，解决N+1问题）"""
        queryset = super().get_queryset()
        if self.request.user.is_authenticated:
            # 使用select_related优化外键查询
            queryset = queryset.filter(user_id=self.request.user.id).select_related(
                'start_attraction'
            )
            # 使用prefetch_related优化收藏关系查询，解决N+1问题
            from django.db.models import Prefetch
            queryset = queryset.prefetch_related(
                Prefetch(
                    'favorited_by',
                    queryset=RouteFavorite.objects.filter(user=self.request.user),
                    to_attr='user_favorites'
                )
            )
            # 使用annotate优化收藏数查询
            from django.db.models import Count
            queryset = queryset.annotate(favorites_count_annotated=Count('favorited_by'))
        return queryset.order_by('-created_at')
    
    @action(detail=True, methods=['post'], permission_classes=[IsAuthenticated])
    def share(self, request, pk=None):
        """分享路线"""
        route_plan = self.get_object()
        
        # 检查是否是路线所有者
        if route_plan.user_id != request.user.id:
            return Response(
                {'error': '无权分享此路线'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        # 生成分享码
        if not route_plan.share_code:
            share_code = get_random_string(32)
            # 确保分享码唯一
            while RoutePlan.objects.filter(share_code=share_code).exists():
                share_code = get_random_string(32)
            route_plan.share_code = share_code
        
        route_plan.is_shared = True
        route_plan.share_count += 1  # 增加分享次数
        route_plan.save()
        
        return Response({
            'message': '分享成功',
            'share_code': route_plan.share_code,
            'share_url': f'/route-share/{route_plan.share_code}',
            'share_count': route_plan.share_count
        }, status=status.HTTP_200_OK)
    
    @action(detail=True, methods=['post'], permission_classes=[IsAuthenticated])
    def unshare(self, request, pk=None):
        """取消分享路线"""
        route_plan = self.get_object()
        
        # 检查是否是路线所有者
        if route_plan.user_id != request.user.id:
            return Response(
                {'error': '无权取消分享此路线'},
                status=status.HTTP_403_FORBIDDEN
            )
        
        route_plan.is_shared = False
        route_plan.save()
        
        return Response({'message': '已取消分享'}, status=status.HTTP_200_OK)
    
    @action(detail=False, methods=['get'], permission_classes=[AllowAny])
    def shared(self, request):
        """获取所有分享的路线 - 公开访问（优化查询）"""
        # 使用select_related优化外键查询，减少数据库查询次数
        shared_routes = RoutePlan.objects.filter(is_shared=True).select_related(
            'start_attraction'
        ).order_by('-created_at')
        serializer = self.get_serializer(shared_routes, many=True)
        return Response(serializer.data)
    
    @action(detail=False, methods=['get'], url_path='recommended', permission_classes=[AllowAny])
    def recommended(self, request):
        """获取推荐路线（热门路线）- 公开访问（优化查询和排序）"""
        
        limit = int(request.query_params.get('limit', 10))
        cache_key = f'recommended_routes_{limit}'
        
        # 尝试从缓存获取
        cached_data = cache.get(cache_key)
        if cached_data:
            return Response(cached_data)
        
        # 获取分享的路线，按综合热度排序（浏览量+分享次数+使用次数）
        queryset = RoutePlan.objects.filter(is_shared=True).select_related(
            'start_attraction'
        ).annotate(
            # 计算综合热度分数
            hot_score=F('view_count') + F('share_count') * 2 + F('use_count') * 3
        ).order_by('-hot_score', '-created_at')[:limit]
        
        serializer = self.get_serializer(queryset, many=True)
        response_data = {
            'count': len(serializer.data),
            'results': serializer.data
        }
        
        # 缓存结果（30分钟）
        cache.set(cache_key, response_data, 1800)
        
        return Response(response_data)
    
    @action(detail=False, methods=['get'], url_path='hot', permission_classes=[AllowAny])
    def hot(self, request):
        """获取热门路线 - 公开访问（优化查询和排序）"""
        from django.core.cache import cache
        
        limit = int(request.query_params.get('limit', 10))
        cache_key = f'hot_routes_{limit}'
        
        # 尝试从缓存获取
        cached_data = cache.get(cache_key)
        if cached_data:
            return Response(cached_data)
        
        # 获取分享的路线，按综合热度排序（浏览量权重最高）
        queryset = RoutePlan.objects.filter(is_shared=True).select_related(
            'start_attraction'
        ).annotate(
            # 计算综合热度分数：浏览量*3 + 分享次数*2 + 使用次数*1
            hot_score=F('view_count') * 3 + F('share_count') * 2 + F('use_count')
        ).order_by('-hot_score', '-created_at')[:limit]
        
        serializer = self.get_serializer(queryset, many=True)
        response_data = {
            'count': len(serializer.data),
            'results': serializer.data
        }
        
        # 缓存结果（30分钟）
        cache.set(cache_key, response_data, 1800)
        
        return Response(response_data)
    
    @action(detail=False, methods=['get'], url_path='by-code/(?P<share_code>[^/.]+)')
    def by_code(self, request, share_code=None):
        """通过分享码获取路线（优化查询和缓存）"""
        cache_key = f'route_by_code_{share_code}'
        
        # 尝试从缓存获取
        cached_data = cache.get(cache_key)
        if cached_data:
            # 异步更新浏览量（不阻塞响应）
            try:
                route_plan = RoutePlan.objects.get(share_code=share_code, is_shared=True)
                route_plan.view_count += 1
                route_plan.save(update_fields=['view_count'])
                # 更新缓存
                cached_data['view_count'] = route_plan.view_count
                cache.set(cache_key, cached_data, 1800)  # 30分钟
            except RoutePlan.DoesNotExist:
                pass
            return Response(cached_data)
        
        try:
            # 使用select_related优化查询
            route_plan = RoutePlan.objects.select_related('start_attraction').get(
                share_code=share_code, 
                is_shared=True
            )
            # 增加浏览量
            route_plan.view_count += 1
            route_plan.save(update_fields=['view_count'])
            serializer = self.get_serializer(route_plan)
            response_data = serializer.data
            
            # 缓存结果（30分钟）
            cache.set(cache_key, response_data, 1800)
            
            return Response(response_data)
        except RoutePlan.DoesNotExist:
            return Response(
                {'error': '分享码无效或路线已取消分享'},
                status=status.HTTP_404_NOT_FOUND
            )
    
    @action(detail=True, methods=['post', 'delete'], permission_classes=[IsAuthenticated])
    def favorite(self, request, pk=None):
        """收藏/取消收藏路线"""
        route_plan = self.get_object()
        user = request.user
        
        if request.method == 'POST':
            # 收藏路线
            favorite, created = RouteFavorite.objects.get_or_create(
                user=user,
                route_plan=route_plan
            )
            if created:
                try:
                    from django.core.cache import cache
                    cache.delete_pattern(f'attraction_recommendations_{user.id}_*')
                    cache.delete_pattern(f'content_based_rec_{user.id}_*')
                except Exception:
                    pass
                return Response({'message': '收藏成功'}, status=status.HTTP_201_CREATED)
            else:
                return Response({'message': '已收藏'}, status=status.HTTP_200_OK)
        
        elif request.method == 'DELETE':
            # 取消收藏
            try:
                favorite = RouteFavorite.objects.get(user=user, route_plan=route_plan)
                favorite.delete()
                try:
                    from django.core.cache import cache
                    cache.delete_pattern(f'attraction_recommendations_{user.id}_*')
                    cache.delete_pattern(f'content_based_rec_{user.id}_*')
                except Exception:
                    pass
                return Response({'message': '取消收藏成功'}, status=status.HTTP_200_OK)
            except RouteFavorite.DoesNotExist:
                return Response(
                    {'error': '未收藏该路线'},
                    status=status.HTTP_404_NOT_FOUND
                )
    
    @action(detail=False, methods=['get'], permission_classes=[IsAuthenticated])
    def favorites(self, request):
        """获取当前用户的收藏路线列表（分页）"""
        from rest_framework.pagination import PageNumberPagination
        favorites_qs = RouteFavorite.objects.filter(user=request.user).select_related(
            'route_plan', 'route_plan__start_attraction'
        ).order_by('-created_at')
        routes_qs = [fav.route_plan for fav in favorites_qs]
        paginator = PageNumberPagination()
        try:
            page_size = int(request.query_params.get('page_size', 20))
        except Exception:
            page_size = 20
        paginator.page_size = page_size
        page = paginator.paginate_queryset(routes_qs, request, view=self)
        serializer = self.get_serializer(page, many=True)
        return paginator.get_paginated_response(serializer.data)
    
    @action(detail=True, methods=['post'], permission_classes=[IsAuthenticated])
    def increment_share(self, request, pk=None):
        """增加分享次数"""
        route_plan = self.get_object()
        route_plan.share_count += 1
        route_plan.save(update_fields=['share_count'])
        return Response({
            'message': '分享次数已更新',
            'share_count': route_plan.share_count
        }, status=status.HTTP_200_OK)
    
    @action(detail=True, methods=['post'], permission_classes=[AllowAny])
    def increment_use(self, request, pk=None):
        """增加使用次数（当用户使用此路线规划时）"""
        try:
            route_plan = RoutePlan.objects.get(pk=pk, is_shared=True)
            route_plan.use_count += 1
            route_plan.save(update_fields=['use_count'])
            return Response({
                'message': '使用次数已更新',
                'use_count': route_plan.use_count
            }, status=status.HTTP_200_OK)
        except RoutePlan.DoesNotExist:
            return Response(
                {'error': '路线不存在'},
                status=status.HTTP_404_NOT_FOUND
            )
class RoutePlanAsyncView(APIView):
    """异步路线规划触发"""
    permission_classes = [IsAuthenticated]

    def post(self, request):
        if not _CELERY_AVAILABLE:
            return Response({'error': 'Celery 未安装或不可用'}, status=status.HTTP_503_SERVICE_UNAVAILABLE)
        payload = {
            'budget': request.data.get('budget', 0),
            'start_attraction_id': request.data.get('start_attraction_id'),
            'must_visit': request.data.get('must_visit_attractions', []) or request.data.get('must_visit', []),
            'priority': request.data.get('priority', 'balanced'),
            'transport_mode': request.data.get('transport_mode', 'driving'),
            'start_time': request.data.get('start_time'),
            'max_total_time': request.data.get('max_total_time'),
            'user_id': request.user.id if request.user.is_authenticated else None
        }
        async_result = plan_route_task.delay(payload)
        return Response({'task_id': async_result.id, 'state': async_result.state}, status=status.HTTP_202_ACCEPTED)


class RoutePlanStatusView(APIView):
    """查询异步路线规划任务状态"""
    permission_classes = [IsAuthenticated]

    def get(self, request):
        if not _CELERY_AVAILABLE:
            return Response({'error': 'Celery 未安装或不可用'}, status=status.HTTP_503_SERVICE_UNAVAILABLE)
        task_id = request.query_params.get('task_id')
        if not task_id:
            return Response({'detail': '缺少 task_id'}, status=status.HTTP_400_BAD_REQUEST)
        result = AsyncResult(task_id)
        if result.ready():
            try:
                data = result.get(timeout=1)
                return Response({'state': 'SUCCESS', 'result': data})
            except Exception as e:
                return Response({'state': 'FAILURE', 'detail': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        return Response({'state': result.state})

